﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace ELab.Hooking
{
    public class KeySimulator
    {

        [DllImport("user32.dll")]
        static extern UInt32 SendInput(UInt32 nInputs, [MarshalAs(UnmanagedType.LPArray, SizeConst = 1)] INPUT[] pInputs, Int32 cbSize);

        [StructLayout(LayoutKind.Sequential)]
        struct KEYBDINPUT
        {
            public short wScan; public int dwFlags;
            public int time; public IntPtr dwExtraInfo;
        }

        [StructLayout(LayoutKind.Explicit)]
        struct INPUT
        {
            [FieldOffset(0)]
            public int type;
            [FieldOffset(8)]
            public KEYBDINPUT ki; //x64 - 8, x32 - 4
        }
        [Flags]
        public enum InputType
        {
            INPUT_MOUSE = 0,
            INPUT_KEYBOARD = 1,
            INPUT_HARDWARE = 2
        }
        [Flags]
        public enum KEYEVENTF
        {
            KEYDOWN = 0,
            EXTENDEDKEY = 0x0001,
            KEYUP = 0x0002,
            UNICODE = 0x0004,
            SCANCODE = 0x0008,
        }
        const int KEYEVENTF_DOWN = 0; //key UP
        const int KEYEVENTF_EXTENDEDKEY = 0x0001;
        const int KEYEVENTF_KEYUP = 0x0002; //key UP
        const int KEYEVENTF_UNICODE = 0x0004;
        const int KEYEVENTF_SCANCODE = 0x0008; // scancode

        public static string  Send_Key(short Keycode)
        {
            INPUT[] InputData = new INPUT[2];
            InputData[0].type = 1;// Input keyboard
            InputData[0].ki.wScan = Keycode;

            //InputData[0].ki.dwFlags = KEYEVENTF_DOWN | KEYEVENTF_SCANCODE;
            //InputData[0].ki.dwFlags = KEYEVENTF_DOWN | KEYEVENTF_UNICODE;
            InputData[0].ki.dwFlags = KEYEVENTF_DOWN ;
            InputData[0].ki.time = 0;
            InputData[0].ki.dwExtraInfo = IntPtr.Zero;


            InputData[1].type = 1;// Input keyboard
            InputData[1].ki.wScan = Keycode;

            //InputData[0].ki.dwFlags = KEYEVENTF_KEYUP | KEYEVENTF_SCANCODE;
            //InputData[0].ki.dwFlags = KEYEVENTF_KEYUP | KEYEVENTF_UNICODE;
            InputData[1].ki.dwFlags = KEYEVENTF_KEYUP ;
            InputData[1].ki.time = 0;
            InputData[1].ki.dwExtraInfo = IntPtr.Zero;

            //SendInput(1, InputData, Marshal.SizeOf(typeof(INPUT)));
            //if (SendInput(2, InputData, Marshal.SizeOf(InputData[0])) == 0)
            if (SendInput(2, InputData,2* Marshal.SizeOf(typeof(INPUT)))==0)
            {
                return "SendInput failed with code: " +
                Marshal.GetLastWin32Error().ToString();
            }
            return "";
        }
        //public static void SendKeyAsInput(System.Windows.Forms.Keys key)
        //{
        //    INPUT structure = new INPUT();
        //    structure.type = (int)InputType.INPUT_KEYBOARD;
        //    structure.ki.wVk = (short)key;
        //    structure.ki.dwFlags = (int)KEYEVENTF.KEYDOWN;
        //    structure.ki.dwExtraInfo = GetMessageExtraInfo();

        //    INPUT input2 = new INPUT();
        //    input2.type = (int)InputType.INPUT_KEYBOARD;
        //    input2.ki.wVk = (short)key;
        //    input2.mi.dwFlags = (int)KEYEVENTF.KEYUP;
        //    input2.ki.dwExtraInfo = GetMessageExtraInfo();

        //    INPUT[] pInputs = new INPUT[] { structure, input2 };

        //    SendInput(2, pInputs, Marshal.SizeOf(structure));
        //}

        //public static void SendKeyAsInput(System.Windows.Forms.Keys key, int HoldTime)
        //{
        //    INPUT INPUT1 = new INPUT();
        //    INPUT1.type = (int)InputType.INPUT_KEYBOARD;
        //    INPUT1.ki.wVk = (short)key;
        //    INPUT1.ki.dwFlags = (int)KEYEVENTF.KEYDOWN;
        //    INPUT1.ki.dwExtraInfo = GetMessageExtraInfo();
        //    SendInput(1, new INPUT[] { INPUT1 }, Marshal.SizeOf(INPUT1));

        //    WaitForSingleObject((IntPtr)0xACEFDB, (uint)HoldTime);

        //    INPUT INPUT2 = new INPUT();
        //    INPUT2.type = (int)InputType.INPUT_KEYBOARD;
        //    INPUT2.ki.wVk = (short)key;
        //    INPUT2.mi.dwFlags = (int)KEYEVENTF.KEYUP;
        //    INPUT2.ki.dwExtraInfo = GetMessageExtraInfo();
        //    SendInput(1, new INPUT[] { INPUT2 }, Marshal.SizeOf(INPUT2));

        //}
    }
}
